/*
 * Permission.java
 *
 * Created on August 1, 2007, 10:03 AM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package org.atomojo.auth.service.db;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.UUID;
import org.infoset.xml.Element;
import org.infoset.xml.ItemConstructor;
import org.infoset.xml.ItemDestination;
import org.infoset.xml.XMLException;
import org.milowski.db.DB;
import org.milowski.db.DBCache;
import org.milowski.db.DBConnection;
import org.milowski.db.DBObject;
import org.milowski.db.DBQueryHandler;

/**
 *
 * @author alex
 */
public class Realm extends DBObject<AuthDB> implements Comparable<Realm>,XMLObject
{

   String name;
   UUID uuid;
   
   /** Creates a new instance of Permission */
   public Realm(AuthDB db,int id,String name,UUID uuid)
   {
      super(db,id);
      this.name = name;
      this.uuid = uuid;
   }
   
   public void delete() 
      throws SQLException
   {
      final DBCache<UUID,Group> groupCache = db.realmGroupCaches.get(this);
      final DBCache<UUID,RealmUser> userCache = db.realmUserCaches.get(this);
      DBConnection connection = db.getConnection();
      try {
         connection.query(AuthDB.GROUP_BY_REALM,new DBQueryHandler() {
            public void prepare(PreparedStatement s)
               throws SQLException
            {
               s.setInt(1,id);
            }
            public void onResults(ResultSet set)
               throws SQLException
            {
               while (set.next()) {
                  Group group = groupCache.get(set.getInt(1));
                  group.delete();
               }
            }
         });
         connection.query(AuthDB.REALM_USER_BY_REALM,new DBQueryHandler() {
            public void prepare(PreparedStatement s)
               throws SQLException
            {
               s.setInt(1,id);
            }
            public void onResults(ResultSet set)
               throws SQLException
            {
               while (set.next()) {
                  RealmUser user = userCache.get(set.getInt(1));
                  user.delete();
               }
            }
         });
         connection.deleteById(AuthDB.DELETE_AUTHENTICATED_BY_REALM, id);
         connection.deleteById(AuthDB.DELETE_REALM, id);
         db.realmCache.remove(id);
         db.realmUserCaches.remove(this);
         db.realmGroupCaches.remove(this);
      } finally {
         db.release(connection);
      }
   }

   public String getName()
   {
      return name;
   }

   public UUID getUUID()
   {
      return uuid;
   }
   
   public int compareTo(Realm other) {
      return uuid.compareTo(other.getUUID());
   }
   
   public boolean equals(Object obj) {
      return obj instanceof Realm && ((Realm)obj).getUUID().equals(uuid);
   }
   
   public void generate(ItemConstructor constructor,ItemDestination dest)
      throws XMLException
   {
      generate(constructor,dest,false);
   }
   
   public void generate(ItemConstructor constructor,ItemDestination dest,boolean recurse)
      throws XMLException
   {
      Element top = constructor.createElement(XML.REALM_NAME);
      top.setAttributeValue("id",uuid.toString());
      top.setAttributeValue("name",name);
      dest.send(top);
      if (recurse) {
         try {
            dest.send(constructor.createCharacters("\n"));
            dest.send(constructor.createElement(XML.USERS_NAME));
            boolean first = true;
            Iterator<RealmUser> users = db.getRealmUsers(this);
            while (users.hasNext()) {
               if (first) {
                  dest.send(constructor.createCharacters("\n"));
                  first = false;
               }
               users.next().generate(constructor,dest);
               dest.send(constructor.createCharacters("\n"));
            }
            dest.send(constructor.createElementEnd(XML.USERS_NAME));
            dest.send(constructor.createCharacters("\n"));
            dest.send(constructor.createElement(XML.GROUPS_NAME));
            first = true;
            Iterator<Group> groups = db.getGroups(this);
            while (groups.hasNext()) {
               if (first) {
                  dest.send(constructor.createCharacters("\n"));
                  first = false;
               }
               groups.next().generate(constructor,dest);
               dest.send(constructor.createCharacters("\n"));
            }
            dest.send(constructor.createElementEnd(XML.GROUPS_NAME));
            dest.send(constructor.createCharacters("\n"));
         } catch (SQLException ex) {
            throw new XMLException("Database error while retrieving users and groups",ex);
         }
      }
      dest.send(constructor.createElementEnd(XML.REALM_NAME));
   }
}
